package at.mri.dogwatch.client.pages.widgets;

import java.util.HashMap;
import java.util.Map;

import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.dom.client.Element;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.ui.Widget;

/**
 * 
 * Chromeless Player API
 * 
 * @author Uwe Maurer
 * 
 */
public class ChromelessPlayer extends Widget {

	public enum PlayerState {
		STOPPED, PLAYING, PAUSED, LOADING, CUED,
	}

	public interface PlayerListener {
		public void onPlayerReady();

		public void onPlayerStateChange(PlayerState state);
	}

	public static PlayerListener emptyListener() {
		return new PlayerListener() {
			@Override
			public void onPlayerReady() {
			}

			@Override
			public void onPlayerStateChange(PlayerState state) {
			}
		};
	}

	public static class YTPlayer extends JavaScriptObject {
		protected YTPlayer() {
		}

		// loadVideoById(videoId:String, startSeconds:Number):Void
		public native final void loadVideoById(String videoId, int startSeconds) /*-{
			this.loadVideoById(videoId, startSeconds);
		}-*/;

		public native final void setSize(int width, int height) /*-{
			this.setSize(width, height);
		}-*/;

		public native final void setVolume(int volume) /*-{
			this.setVolume(volume);
		}-*/;

		public native final void playVideo() /*-{
			this.playVideo()
		}-*/;

		public native final double getCurrentTime() /*-{
			return this.getCurrentTime();
		}-*/;

		public native final void pauseVideo() /*-{
			this.pauseVideo();
		}-*/;

		public native final void stopVideo() /*-{
			this.stopVideo();
		}-*/;

		public native final void loadVideoById(String videoId) /*-{
			this.loadVideoById(videoId);
		}-*/;

	}

	private static final Map<String, ChromelessPlayer> map = new HashMap<String, ChromelessPlayer>();

	static {
		register();
	}

	public static void onReady(String playerId, YTPlayer playerElement) {
		ChromelessPlayer player = map.get(playerId);
		if (player != null) {
			player.player = playerElement;
			if (player.listener != null) {
				player.listener.onPlayerReady();
			}
		}
	}

	public static void onStateChange(String playerId, int state) {
		ChromelessPlayer player = map.get(playerId);
		if (player != null && player.listener != null && state >= 0
				&& state < PlayerState.values().length) {
			player.listener.onPlayerStateChange(PlayerState.values()[state]);
		}
	}

	private static native void register() /*-{
		$wnd.onYouTubePlayerReady = function(playerId) {
			var ytplayer = $wnd.document.getElementById(playerId + "api");
			@at.mri.dogwatch.client.pages.widgets.ChromelessPlayer::onReady(Ljava/lang/String;Lat/mri/dogwatch/client/pages/widgets/ChromelessPlayer$YTPlayer;)(playerId, ytplayer);
			var name = 'onPlayerStateChange' + playerId;
			$wnd[name] = function(state) {
				@at.mri.dogwatch.client.pages.widgets.ChromelessPlayer::onStateChange(Ljava/lang/String;I)(playerId, state);
			}
			ytplayer.addEventListener("onStateChange", name);
		}
	}-*/;

	private final String name;

	private YTPlayer player;
	private PlayerListener listener;

	public ChromelessPlayer(String elementName) {
		Element elem = DOM.createDiv();
		elem.setId(elementName);
		setElement(elem);
		this.name = elementName;
		map.put(elementName, this);
	}

	public void createSwf(String videoId, int width, int height,
			PlayerListener listener) {
		this.listener = listener;
		/*
		 * 0 ... videoId 1 ... jspApi (1,0} 2 ... controls (1,0) 3 ... related
		 * at end 4 ... show info 5 ... load policy 6 ... autohide 7 ...
		 * playerId
		 */

		String[] videoLinkParams = { videoId, // videoID
				"0", // jspAPI
				"1", // Controls
				"0", // related at end
				"0", // show info
				"3", // load policy
				"1", // autohide
				name // playerid
		};

		String videoLink = "http://www.youtube.com/e/"
				+ videoLinkParams[0] + "?enablejsapi=" + videoLinkParams[1]
				+ "&controls=" + videoLinkParams[2] + "&rel="
				+ videoLinkParams[3] + "&showinfo=" + videoLinkParams[4]
				+ "&iv_load_policy=" + videoLinkParams[5] + "&autohide="
				+ videoLinkParams[6] + "&playerapiid=" + videoLinkParams[7];
		createSwf(name, width, height, videoLink);
	}

	/**
	 * THIS WORKS WITH loadVideoById(...)
	 * 
	 * var params = { allowScriptAccess : "always", bgcolor : "#000000", wmode :
	 * "opaque" }; var atts = { id : name + "api" };
	 * 
	 * $wnd.swfobject.embedSWF(
	 * "http://www.youtube.com/apiplayer?enablejsapi=1&playerapiid=" + name,
	 * name, "" + width, "" + height, "8", null, null, params, atts);
	 * 
	 */

	private native void createSwf(String name, int width, int height,
			String videoLink) /*-{
		var params = {
			allowScriptAccess : "always",
			allowFullScreen : "false",
			bgcolor : "#000000",
			wmode : "opaque"
		};
		var atts = {
			id : name + "api"
		};
		$wnd.swfobject.embedSWF(videoLink, name, "" + width, "" + height, "8",
				null, null, params, atts);
	}-*/;

	public void loadVideoById(String videoId, int startSeconds) {
		// if (player != null) {
		// player.loadVideoById(videoId, startSeconds);
		// }
	}

	public void loadVideoById(String videoId) {
		// if (player != null){
		// player.loadVideoById(videoId);
		// }
	}

	public void setSize(int width, int height) {
		if (player != null) {
			player.setSize(width, height);
		}
	}

	public void setVolume(int volume) {
		if (player != null) {
			player.setVolume(volume);
		}
	}

	public void playVideo() {
		if (player != null) {
			player.playVideo();
		}
	}

	public void pauseVideo() {
		if (player != null) {
			player.pauseVideo();
		}
	}

	public void stopVideo() {
		if (player != null) {
			player.stopVideo();
		}
	}

	public Element getPlayer() {
		return player.cast();
	}

	public double getCurrentTime() {
		return player.getCurrentTime();
	}

}
